
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//棋盘初始化函数
//Chessboard棋盘数组，ln=棋盘大小,成功返回Chessboard，不成功NULL
void init_Chessboard(char Chessboard[][7], int ln)
{
    if ((Chessboard != NULL) && (ln > 0)) {
        int i = 0, j = 0;
        for (i = 0; i < ln; ++i) {
            for (j = 0; j < ln; ++j) {
                Chessboard[i][j] = '\t'; 
            }
        }
        // return Chessboard;
    }
    // return NULL;  
}


//显示棋盘函数
void show_Chessboard(char Chessboard[][7], int ln)
{
    assert((Chessboard != NULL) && (ln > 0));

    int i = 0, j = 0;
    for (i = 0; i < ln; ++i) {
        putchar('\t');
        putchar(i + '0');
    }//end for1
    putchar('\n');
    putchar('\n');

    for (i = 0; i < ln; ++i) {
        putchar(i + '0');
        for (j = 0; j < ln; ++j) {
            if ('\t' == Chessboard[i][j]) {
                putchar(Chessboard[i][j]);
            }
            else
            {
                putchar('\t');
                putchar(Chessboard[i][j]);
            }

        }
        putchar('\n');
        putchar('\n');
    }//end for2
}

//棋子下子函数
//下子成功返回1，不成功返回0
int play(char Chessboard[][7], int ln, int x, int y, char ChessPieces)
{
    assert(Chessboard); //ChessPieces=NULL跳出
    if ((x < ln) && (y < ln) && (x >= 0) && (y >= 0)) {
        if ('\t' == Chessboard[x][y]) {

            Chessboard[x][y] = ChessPieces;
            return 1;  //成功
        }
        else
        {
            return 0;
        }//end if2
    }//end if1
    return 0;
}

//满盘判断
//棋盘满了判断//满了就返回-1
int full_Chess(char Chessboard[][7], int ln)
{
    int i = 0, j = 0;
    for (i = 0; i < ln; ++i) {
        for (j = 0; j < ln; ++j) {
            if ('\t' == Chessboard[i][j]) {
                return 0;  //棋盘未满
            }//end if
        }//end for j
    }//end for i

    return 1;//棋盘满了

}


//是否连成五子线判断函数
//Chessboard=棋盘数组,ln=棋盘宽度,(XS,YS)方向判断起点坐标,(dx,dy)方向增量标记
//连成线返回1，没有返回0
int judga_line(char Chessboard[][7], int ln, int XS, int YS, int dx, int dy)
{
    assert((Chessboard != NULL) && (ln > 0));
    if ((XS < ln) && (YS < ln)  //起点坐标在棋盘内
        && (XS >= 0) && (YS >= 0)
        && (dx != 0 || dy != 0))        //坐标增量不为同时0
    {

        if (((XS + dx * 4) > ln) || ((XS + dx * 4) < 0) || //判断终点坐标
            ((YS + dy * 4) > ln) || ((YS + dy * 4) < 0) || //在棋盘外
            ('\t' == Chessboard[XS][YS]))
        {
            return 0;  //不在棋盘内，或者起点是没下子
        }
        else
        {
            int i = 0;
            for (i = 1; i < 5; ++i) {
                if (Chessboard[XS][YS] != Chessboard[XS + (dx * i)][YS + (dy * i)])
                {
                    return 0;  //如果不是连续5个一样的
                }//end if3
            }//end for1
            return 1;  //五个都一样，且都在棋盘内
        }//end if 2
    }
    return 0;  //其他情况
}

//裁判函数
//Chessboard 棋盘数组，ln=棋盘宽度
//赢了返回1，否则返回0
int judga(char Chessboard[][7], int ln)
{
    assert((NULL != Chessboard) && (ln > 0));
    int i = 0, j = 0;
    //纵向成五子连线判断
    for (i = 0; i < (ln - 4); ++i) {
        for (j = 0; j < ln; ++j) {
            if (judga_line(Chessboard, ln, i, j, 1, 0)) {
                return 1;
            }
        }//end for_j
    }//end for_i

      //横向成五子连线判断
    for (i = 0; i < ln; ++i) {
        for (j = 0; j < (ln - 4); ++j) {
            if (judga_line(Chessboard, ln, i, j, 0, 1)) {
                return 1;
            }
        }//end for_j
    }//end for_i

      //左上到右下成五子连线判断
    for (i = 0; i < (ln - 4); ++i) {
        for (j = 0; j < (ln - 4); ++j) {
            if (judga_line(Chessboard, ln, i, j, 1, 1)) {
                return 1;
            }
        }//end for_j
    }//end for_i

      //左下到右上成五子连线判断
    for (i = ln - 1; i > (ln - 4); --i) {
        for (j = 0; j < (ln - 4); ++j) {
            if (judga_line(Chessboard, ln, i, j, -1, 1)) {
                return 1;
            }
        }//end for_j
    }//end for_i

    return 0;  //没能赢
}


//主函数


int main()
{
    char CB[7][7];
    char nameA[50] = "玩家A";
    char nameB[50] = "玩家B";
    int x = -1, y = -1;
    //初始化
    init_Chessboard(CB, 7);

    printf("请输入玩家A的名字:");
    scanf("%s", nameA);

    printf("请输入玩家B的名字:");
    scanf("%s", nameB);

    //显示棋盘
    show_Chessboard(CB, 7);

    while (1) {
        //判断是否棋盘已满
        if (full_Chess(CB, 7)) {
            puts("\n棋盘已满，下次再战！");
            break; //跳出最外层while
        }//end if


        //玩家Ａ下子
        while (1) {
            printf("\n请玩家 %s 下子 @\n", nameA);
            printf("棋子行坐标X=");
            scanf("%d", &x);
            printf("棋子列坐标Y=");
            scanf("%d", &y);

            if (play(CB, 7, x, y, '@')) {  //@ ascii=64
                break;   //下子成功
            }
            else
            {
                puts("下子失败，请重新选定位置下子");
                continue;  //下子不成功，重新下子
            }//end if
        }//end while A

        //显示棋盘
        show_Chessboard(CB, 7);

        //判断玩家A是否胜利
        if (judga(CB, 7)) {
            printf("\n恭喜玩家 %s 成功取得胜利！！鲜花\n", nameA);
            getchar();
            getchar();
            break; //跳出最外层while
        }//不用下了

        //玩家B下子
        while (1) {
            printf("\n请玩家 %s 下子 O\n", nameB);
            printf("棋子行坐标X=");
            scanf("%d", &x);
            printf("棋子列坐标Y=");
            scanf("%d", &y);

            if ((play(CB, 7, x, y, 'O'))) { //O ascii=79
                break;   //下子成功
            }
            else
            {
                puts("下子失败，请重新选定位置下子");
                continue;  //下子不成功，重新下子
            }//end if

        }//end while B

        //显示棋盘
        show_Chessboard(CB, 7);

        //判断玩家B是否胜利
        if (judga(CB, 7)) {
            printf("\n恭喜玩家 %s 成功取得胜利！！ 鲜花\n", nameA);
            getchar();
            getchar();
            break; //跳出最外层while
        }//不用下了

    }

    return 0;

}                     //五子棋